/**
 *  Copyright 2010 Kyle O'Connor, Justin Arling, Mike Mercieca
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package edu.drexel.sd0910.ece01.aqmon.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.WindowListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import javax.swing.border.EtchedBorder;

import org.apache.log4j.Logger;

import edu.drexel.sd0910.ece01.aqmon.gui.wizard.Wizard;
import edu.drexel.sd0910.ece01.aqmon.gui.wizard.WizardPanelDescriptor;
import edu.drexel.sd0910.ece01.aqmon.gui.wizard.impl.MapPanelDescriptor;
import edu.drexel.sd0910.ece01.aqmon.gui.wizard.impl.NodeDiscoveryPanelDescriptor;
import edu.drexel.sd0910.ece01.aqmon.gui.wizard.impl.PortChooserPanelDescriptor;
import edu.drexel.sd0910.ece01.aqmon.gui.wizard.impl.SummaryPanelDescriptor;
import edu.drexel.sd0910.ece01.aqmon.gui.wizard.impl.WelcomePanelDescriptor;
import edu.drexel.sd0910.ece01.aqmon.util.ImageUtils;

/**
 * Main GUI window - View component (MVC pattern)<br>
 * This class implements the main GUI code and the setup
 * <code>{@link Wizard}</code> implementation. This class implements the
 * <code>{@link Observer}</code> interface for communication with the model.
 * 
 * @author Kyle O'Connor
 * 
 */
@SuppressWarnings("serial")
public class MainView extends JFrame implements Observer {

	private final static Logger log = Logger.getLogger(MainView.class);

	// gui components
	private Wizard setupWizard;
	// private JPanel contentPanel;
	private JLabel statusBar;
	private JSeparator statusBarSeparator;
	private JLabel statusBarTime;
	private JLabel appTitle;
	private JButton exitButton;

	// data model
	private MainModel model;

	public MainView(MainModel aModel) throws HeadlessException {
		model = aModel;
		initSetupWizard();
		initComponents();
	}

	public MainView(String title, MainModel aModel) throws HeadlessException {
		super(title);
		model = aModel;
		initSetupWizard();
		initComponents();
	}

	private void initSetupWizard() {
		setupWizard = new Wizard();

		WizardPanelDescriptor wizardMain = new WelcomePanelDescriptor(model);
		setupWizard.registerWizardPanel(WelcomePanelDescriptor.IDENTIFIER, wizardMain);
		PortChooserPanelDescriptor wizardStep1 = new PortChooserPanelDescriptor(model);
		setupWizard.registerWizardPanel(PortChooserPanelDescriptor.IDENTIFIER, wizardStep1);
		WizardPanelDescriptor wizardStep2 = new NodeDiscoveryPanelDescriptor(model);
		setupWizard.registerWizardPanel(NodeDiscoveryPanelDescriptor.IDENTIFIER, wizardStep2);
		WizardPanelDescriptor wizardStep3 = new MapPanelDescriptor(model);
		setupWizard.registerWizardPanel(MapPanelDescriptor.IDENTIFIER, wizardStep3);
		WizardPanelDescriptor wizardSummary = new SummaryPanelDescriptor(model);
		setupWizard.registerWizardPanel(SummaryPanelDescriptor.IDENTIFIER, wizardSummary);

		setupWizard.setCurrentPanel(WelcomePanelDescriptor.IDENTIFIER);
	}

	private void initComponents() {
		// setup this frame
		setTitle("AQMon");
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		// set up a full screen window based on resolution
		setUndecorated(true);
		setLayout(new BorderLayout(0, 0)); // borderlayout with spacing (tried vgap=10)
		
		//get screen size (resolution) from java
		Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
		setSize(screenDim);
		setPreferredSize(screenDim);

		// set up main panels
		// contentPanel = new JPanel();
		JPanel statusBarPane = new JPanel(new BorderLayout());
		JPanel titleBarPane = new JPanel(new BorderLayout());

		// define title bar at top
		appTitle = new JLabel("Air Quality Sensor Network - Base Station");
		appTitle.setFont(new Font(appTitle.getFont().getFontName(), Font.BOLD, 32));
		ImageIcon exitIcon = ImageUtils.createImageIcon("/exit_icon.png", "Exit Program");
		exitButton = new JButton(exitIcon);
		exitButton.setActionCommand(GUICommands.EXIT);
		// make exit button undecorated
		exitButton.setBorderPainted(false);
		exitButton.setRolloverEnabled(false);
		exitButton.setOpaque(false);
		exitButton.setContentAreaFilled(false);
		exitButton.setFocusable(false);
		titleBarPane.add(appTitle, BorderLayout.WEST);
		titleBarPane.add(exitButton, BorderLayout.EAST);
		// statusbar
		statusBar = new JLabel(model.getStatusText());
		statusBarSeparator = new JSeparator(JSeparator.VERTICAL);
		statusBarSeparator.setForeground(Color.GRAY);
		statusBarTime = new JLabel("current time");
		// make it look like a statusbar
		statusBarPane.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
		JPanel statusBarSub = new JPanel(new BorderLayout(5, 0));
		statusBarSub.add(statusBarSeparator, BorderLayout.WEST);
		statusBarSub.add(statusBarTime, BorderLayout.EAST);
		statusBarPane.add(statusBarSub, BorderLayout.EAST);
		statusBarPane.add(statusBar, BorderLayout.WEST);

		// start a thread to update the time every second
		new Thread("Time Update Thread") {
			public void run() {
				while (true) {
					Calendar cal = Calendar.getInstance();
					SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy h:mm a");
					statusBarTime.setText(sdf.format(cal.getTime()));
					try {
						sleep(10000);
					} catch (InterruptedException e) {
						log.error(e.toString());
					}
				}
			}
		}.start(); // start it

		// // temporary placeholder for content
		// contentPanel.add(new JLabel("MAIN CONTENT PANEL", JLabel.CENTER));
		// contentPanel.setBorder(BorderFactory.createLineBorder(Color.black));

		add(titleBarPane, BorderLayout.NORTH);
		add(statusBarPane, BorderLayout.SOUTH);
		add(setupWizard, BorderLayout.CENTER);
		this.pack();
	}

	public Wizard getWizard() {
		return setupWizard;
	}

	public void registerWindowControl(WindowListener listener) {
		this.addWindowListener(listener);
	}

	public void registerUIControl(ActionListener listener) {
		exitButton.addActionListener(listener);
		setupWizard.registerUIControl(listener);
	}

	public void showError(String errMessage) {
		JOptionPane.showMessageDialog(this, errMessage);
	}

	public int showDialog(String msg) {
		return JOptionPane.showConfirmDialog(this, msg, "Select an Option", JOptionPane.YES_NO_OPTION);
	}

	private void updateStatusBar() {
		// should be called from event dispatch thread
		if (!javax.swing.SwingUtilities.isEventDispatchThread())
			log.warn("Trying to update status bar outside of event dispatch thread!");

		statusBar.setText(model.getStatusText());
	}

	public void update(Observable o, Object arg) {
		if (arg instanceof String) {
			//log.debug("Model updated (" + arg + ")");

			if (arg.equals(GUIUpdates.STATUS_BAR)) {
				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						updateStatusBar();
					}
				});
			}
		}
	}

}
